﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using MySql.Data;
using MySql.Data.MySqlClient;
using System.Configuration;
using DetetiveKGB.Models.SqlResources;
using System.Web.Security;
using System.Data;

namespace DetetiveKGB.Models
{
    public class LoginModel
    {
        public int LoginId { get; set; }
        
        [Required(ErrorMessage="O usuário é obrigatório.")]
        [DisplayName("Usuário")]
        public string UserName { get; set; }

        public string ApplicationName { get; set; }

        public string Email { get; set; }

        public string Notes { get; set; }

        [Required(ErrorMessage="A senha é obrigatória.")]
        [DataType(DataType.Password)]
        [DisplayName("Senha")]
        public string Password { get; set; }

        [DisplayName("Pergunta")]
        public string Question { get; set; }

        [DisplayName("Resposta")]
        public string Answer { get; set; }

        public bool IsAproved { get; set; }

        public DateTime LastActivityDate { get; set; }
        public DateTime LastLoginDate { get; set; }
        public DateTime LastPasswordChange { get; set; }
        public DateTime CreatedOn { get; set; }
        public bool IsLockedOut { get; set; }
        public DateTime LastLockedOutDate { get; set; }
        public int FailedAttemptCount { get; set; }
        public DateTime FailedAttemptWindow { get; set; }
        public int FailedAttemptAnswerCount { get; set; }
        public DateTime FailedAttemptAnswerWindow { get; set; }

        public void Add()
        {
            MySqlConnection cn  = new MySqlConnection(ConfigurationManager.ConnectionStrings["MySQL"].ConnectionString);
            MySqlCommand cm     = new MySqlCommand(SqlResources.SqlWeapon.Add, cn);
            try
            {
                cn.Open();
                cm.Parameters.AddWithValue("username", this.UserName);
                cm.Parameters.AddWithValue("email", this.Email);
                cm.Parameters.AddWithValue("notes", this.Notes);
                cm.Parameters.AddWithValue("createdOn", DateTime.Now);
                cm.Parameters.AddWithValue("isLockedOut", this.IsLockedOut);
                cm.ExecuteNonQuery();
            }
            catch (MySqlException e)
            {
                throw e;
            }
            finally
            {
                cm.Dispose();
                cn.Dispose();
            }
        }

        public void Update()
        { 
        }

        public static LoginModel Get(string username)
        {
            LoginModel result = null;
            using (MySqlConnection cn = new MySqlConnection(ConfigurationManager.ConnectionStrings["MySQL"].ConnectionString))
            {
                using (MySqlCommand cmd = new MySqlCommand(SqlResources.SqlLogin.Get, cn))
                {
                    try
                    {
                        MySqlDataReader dr = null;
                        cn.Open();
                        cmd.Parameters.AddWithValue("username", username);
                        dr = cmd.ExecuteReader(CommandBehavior.SingleRow);

                        if (dr.Read())
                        {
                            result = new LoginModel()
                            {
                                LoginId = dr.GetInt32(0),
                                UserName = dr.GetString(1),
                                ApplicationName = dr.GetString(2),
                                Email = dr.GetString(3),
                                Notes = dr.IsDBNull(4) ? string.Empty : dr.GetString(4),
                                Password = dr.GetString(5),
                                Question = dr.GetString(6),
                                Answer = dr.GetString(7),
                                CreatedOn = dr.GetDateTime(8),
                                IsLockedOut = dr.GetBoolean(9),
                                FailedAttemptCount = dr.GetInt32(10),
                                FailedAttemptAnswerCount = dr.GetInt32(11)
                            };
                        }
                    }
                    catch (MySqlException ex)
                    {
                        throw ex;
                    }
                }
            }
            return result;
        }

        public static List<LoginModel> ListAll()
        {
            List<LoginModel> result = new List<LoginModel>();
            MySqlConnection cn = new MySqlConnection(ConfigurationManager.ConnectionStrings["MySQL"].ConnectionString);
            MySqlCommand cm = new MySqlCommand(SqlResources.SqlLogin.ListAll, cn);
            MySqlDataReader dr = null;
            try
            {
                cn.Open();
                dr = cm.ExecuteReader();

                while (dr.Read())
                {
                    LoginModel am = new LoginModel()
                    {
                        LoginId     = dr.GetInt32(0),
                        UserName    = dr.GetString(1),
                        Email       = dr.GetString(2),
                        Notes       =dr.IsDBNull(3) ? string.Empty : dr.GetString(3),
                        IsLockedOut = dr.GetBoolean(4)
                    };
                    result.Add(am);
                }
            }
            catch (MySqlException e)
            {
                throw e;
            }
            finally
            {
                dr.Close();
                cm.Dispose();
                cn.Dispose();
            }
            return result;
        }

        public static bool Exists(string username)
        {
            bool result = false;
            MySqlConnection cn = new MySqlConnection(ConfigurationManager.ConnectionStrings["MySQL"].ConnectionString);
            MySqlCommand cm = new MySqlCommand(SqlResources.SqlLogin.Exists, cn);
            try
            {
                cn.Open();
                cm.Parameters.AddWithValue("username", username);
                result = Convert.ToInt32(cm.ExecuteScalar()) > 0;
            }
            catch (MySqlException e)
            {
                throw e;
            }
            finally
            {
                cm.Dispose();
                cn.Dispose();
            }
            return result;
        }

        public static string GetPassword(string username, string question, string answer)
        {
            string result = string.Empty;
            MySqlConnection cn = new MySqlConnection(ConfigurationManager.ConnectionStrings["MySQL"].ConnectionString);
            MySqlCommand cm = new MySqlCommand(SqlResources.SqlLogin.GetPassword, cn);
            try
            {
                cn.Open();
                cm.Parameters.AddWithValue("username", username);
                cm.Parameters.AddWithValue("question", question);
                cm.Parameters.AddWithValue("answer", answer);
                result = Convert.ToString(cm.ExecuteScalar());
            }
            catch (MySqlException e)
            {
                throw e;
            }
            finally
            {
                cm.Dispose();
                cn.Dispose();
            }
            return result;
        }
    }

    public interface IMembershipService
    {
        int MinPasswordLength { get; }
        bool ValidateUser(string userName, string password);
    }

    public class LoginMembershipService : IMembershipService
    {
        private readonly MembershipProvider _provider;
        public LoginMembershipService()
            : this(null)
        { 
        }
        public LoginMembershipService(MembershipProvider provider)
        {
            _provider = provider ?? Membership.Provider;
        }
        public int MinPasswordLength
        {
            get 
            {
                return _provider.MinRequiredPasswordLength;
            }
        }

        public bool ValidateUser(string userName, string password)
        {
            bool isValid = false;
            MySqlConnection cn = new MySqlConnection(ConfigurationManager.ConnectionStrings["MySQL"].ConnectionString);
            cn.Open();
            MySqlCommand cmd = new MySqlCommand(SqlLogin.ValidateUser, cn);
                
            cmd.Parameters.AddWithValue("username", userName);
            cmd.Parameters.AddWithValue("password", password);

            try
            {
                object result = cmd.ExecuteScalar();
                isValid = Convert.ToBoolean(result);
            }
            catch
            {
                return false;
            }
            finally
            {
                cmd.Dispose();
                cn.Dispose();
            }
            return isValid;
        }

        public System.Web.Security.MembershipCreateStatus CreateUser(string userName, string password, string email)
        {
            throw new NotImplementedException();
        }

        public bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            throw new NotImplementedException();
        }
    }

    public interface IFormsAuthenticationService
    {
        void SignIn(string userName, bool createPersistentCookie);
        void SignOut();
    }
    public class FormsAuthenticationService : IFormsAuthenticationService
    {
        public void SignIn(string userName, bool createPersistentCookie)
        {
            if (string.IsNullOrEmpty(userName)) throw new ArgumentException("O nome do usuário não pode ser vazio.", "userName");
            FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
        }

        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }
    }
}